﻿using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using ZSZ.Application.IService;
using ZSZ.Core.Entities;
using ZSZ.DTO;
using ZSZ.EntityFramework;
using ZSZ.Service;

namespace ZSZ.Application.Service
{
    public class RoleService : Repository<RoleEntity>, IRoleService
    {
        private readonly ZSZDbContext _ctx = null;
        public long AddNew(string roleName)
        {
           
            bool exists = GetAllDataEntity().Any(r => r.Name == roleName);
            //正常情况不应该执行这个异常，因为UI层应该把这些情况处理好
            //这里只是“把好最后一关”
            if (exists)
            {
                throw new ArgumentException("角色名字已经存在"+roleName);
            }
            RoleEntity role = new RoleEntity
            {
                Name = roleName
            };
            SaveOrUpdate(role,true);
            return role.Id;
            
        }

        public void AddRoleIds(long adminUserId, long[] roleIds)
        {
            var userBS 
                = new BaseService<AdminUserEntity>(_ctx);
            var user = userBS.GetById(adminUserId);
            if(user==null)
            {
                throw new ArgumentException("用户不存在" + adminUserId);
            }
            var roles = GetAllDataEntity().Where(r=>roleIds.Contains(r.Id)).ToArray();
            foreach(var role in roles)
            {
                var adminUserRole = new AdminUserRoleEntity
                {
                    AdminUserId = adminUserId,
                    RoleId = role.Id
                };
                user.AdminUserRoles.Add(adminUserRole);
            }

            _ctx.AdminUsers.Attach(user);
            _ctx.Entry(user).State = EntityState.Modified;
            
        }

        private RoleDTO ToDTO(RoleEntity en)
        {
            var dto = new RoleDTO
            {
                CreateDateTime = en.CreateDateTime,
                Id = en.Id,
                Name = en.Name
            };
            return dto;
        }

        public RoleDTO[] GetAll()
        {
            return GetAllDataEntity().ToList().Select(p => ToDTO(p)).ToArray();
        }

        public RoleDTO[] GetByAdminUserId(long adminUserId)
        {
            var bs = new BaseService<AdminUserEntity>(_ctx);
            var user = bs.GetById(adminUserId);
            if(user==null)
            {
                throw new ArgumentException("不存在的管理员"+adminUserId);
            }
            return user.AdminUserRoles.Select(s => s.Role).ToList().Select(r=>ToDTO(r)).ToArray();
            
        }

        public RoleDTO GetById(long id)
        {
            var role = GetOneById(id);
            return role == null ? null : ToDTO(role);
        }

        public RoleDTO GetByName(string name)
        {
           
            var role = GetAllDataEntity().SingleOrDefault(r => r.Name == name);
            return role == null ? null : ToDTO(role);
            
        }

        public void MarkDeleted(long roleId)
        {
            DeleteById(roleId);
        }

        public void Update(long roleId, string roleName)
        {
            
            bool exists = GetAllDataEntity().Any(r=>r.Name==roleName&&r.Id!=roleId);
            //正常情况不应该执行这个异常，因为UI层应该把这些情况处理好
            //这里只是“把好最后一关”
            if (exists)
            {
                throw new ArgumentException("");
            }
            var role = new RoleEntity
            {
                Id = roleId
            };
            _ctx.Entry(role).State = EntityState.Unchanged;
            role.Name = roleName;
            _ctx.SaveChanges();
            
        }

        public void UpdateRoleIds(long adminUserId, long[] roleIds)
        {
            
            var userBS
                = new BaseService<AdminUserEntity>(_ctx);
            var user = userBS.GetById(adminUserId);
            if (user == null)
            {
                throw new ArgumentException("用户不存在" + adminUserId);
            }
            user.AdminUserRoles.Clear();
            
            var roles = GetAllDataEntity().Where(r => roleIds.Contains(r.Id)).ToArray();
            foreach (var role in roles)
            {
                var adminUserRole = new AdminUserRoleEntity
                {
                    AdminUserId = adminUserId,
                    RoleId = role.Id
                };
                user.AdminUserRoles.Add(adminUserRole);
            }

            _ctx.AdminUsers.Attach(user);
            _ctx.Entry(user).State = EntityState.Modified;
        }

        public RoleService(ZSZDbContext context) : base(context)
        {
            _ctx = context;
        }
    }
}
